<?php

class FRM_Tools_GoogleSiteMap {
	
	protected $flux; //XML String
	protected $nl; //New Line
	protected $listfreq; //Frequency List
	

	/** 
	 * Constructor. Initialize this class and start the XML Google Site Map String.
	 * @return	Void
	 */
	public function __construct() {
		$this->ini ();
		$this->startMap ();
	}
	
	/*-------------------------------------------------PUBLIC FUNCTIONS-------------------------------*/
	
	/** 
	 * This function add url elements to the XML Google Site Map String.
	 * This function is able to determine the format of the input data automatically.
	 * So you can have mixed data !
	 *
	 * @param	Mixed	$o	The object to convert to url.
	 * This can be a string, an array, an associative array, a folder, a mysql resource...
	 * You can extend it !
	 * 
	 * @param	Array 	$option	This parameter is optional and can be used to add extra options (Browse recursively fr exemple) 
	 *
	 * @return	Void
	 */
	
	function add($o, $option = array()) {
		$type = gettype ( $o );
		switch ($type) {
			case "array" :
				if ($this->isMultiDimensional ( $o )) {
					for($i = 0; $i < count ( $o ); $i ++) {
						$this->add ( $o [$i], $option );
					}
				} else {
					
					$this->addURL ( $o, $option );
				}
				break;
			default :
				$this->addURL ( $o, $option );
				break;
		}
	}
	
	/** 
	 * This function close the XML Google Site Map String.
	 * 
	 * @return	String	The XML String
	 */
	function close() {
		$this->flux .= "</urlset>";
		$this->ToString ();
	}
	
	/** 
	 * This function output the XML Google Site Map String to the browser with XML Content-Type
	 * 
	 * @return	Void
	 */
	function view() {
		header ( "Pragma: no-cache" );
		header ( "Content-Type: text/xml;charset=UTF-8" );
		echo $this->flux;
	}
	
	/** 
	 * This function return the XML Google Site Map String (Usefull for debug too)
	 * 
	 * @param	String 	The path to write the file.
	 *
	 * @return	Void 
	 */
	function toString() {
		return $this->flux;
	}
	
	/** 
	 * This function write the XML Google Site Map String in a specified file
	 * 
	 * @return	Void
	 */
	function write($file) {
		$this->makerFile ( $file, $this->flux );
	}
	
	/*-------------------------------------------------PRIVATE FUNCTIONS-------------------------------*/
	
	/** 
	 * This function initialise this class
	 * 
	 * @return	Void
	 */
	function ini() {
		$this->flux = "";
		$this->nl = "\n";
		$this->listfreq = array ("always", "hourly", "daily", "weekly", "monthly", "yearly", "never" );
	
	}
	/** 
	 * This function start the XML Google Site Map String.
	 * 
	 * @return	Void
	 */
	function startMap() {
		$this->flux .= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" . $this->nl;
		$this->flux .= "<urlset xmlns=\"http://www.google.com/schemas/sitemap/0.84\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.google.com/schemas/sitemap/0.84 http://www.google.com/schemas/sitemap/0.84/sitemap.xsd\">" . $this->nl;
	}
	
	/** 
	 * This function can determine the input data and convert them.
	 *
	 * @param	Mixed	$o	The object to convert to url.
	 * This can be a string, an array, an associative array, a folder, a mysql resource...
	 * You can extend it !
	 * 
	 * @param	Array 	$option	This parameter is optional and can be used to add extra options (Browse recursively for exemple) 
	 *
	 * @return	Void
	 */
	function addURL($o, $option = array()) {
		
		$type = gettype ( $o );
		switch ($type) {
			
			case "string" :
				is_dir ( $o ) ? $this->addFolderURL ( $o, $option ) : $this->addStringURL ( $o );
				break;
			
			case "array" :
				$this->addArrayURL ( $o );
				break;
			case "resource" :
				switch (get_resource_type ( $o )) {
					case "mysql result" :
						$this->addMysqlURL ( $o );
						break;
				}
				break;
			
			default :
				break;
		}
	
	}
	/** 
	 * String parser function
	 *
	 * @param	String	$s	The String to parse
	 * 
	 * @return	Void
	 */
	function addStringURL($s) {
		$this->flux .= "<url>" . $this->nl;
		$this->flux .= "<loc>" . $this->cleanURL ( $s ) . "</loc>" . $this->nl;
		$this->flux .= "</url>" . $this->nl;
	}
	/** 
	 * Array parser function. This function can distinct array of associative array.
	 *
	 * @param	Array	$a	The Array to parse
	 * 
	 * @return	Void
	 */
	function addArrayURL($a) {
		
		if ($this->IsAssocArray ( $a )) {
			$this->flux .= "<url>" . $this->nl;
			while ( list ( $k, $v ) = each ( $a ) ) {
				switch ($k) {
					case "loc" :
						$v = $this->cleanURL ( $v );
						break;
					case "lastmod" :
						$v = ($v == "") ? date ( "c" ) : $v;
						break;
					case "changefreq" :
						$v = (in_array ( $v, $this->listfreq )) ? $v : "monthly";
						break;
					case "priority" :
						$v = ($v == "" || $v > 1 || $v < 0) ? "0.5" : number_format ( $v, 1 );
						break;
				}
				
				$this->flux .= "<" . $k . ">" . $v . "</" . $k . ">" . $this->nl;
			}
			$this->flux .= "</url>" . $this->nl;
		} else {
			$this->flux .= "<url>" . $this->nl;
			if ($a [0] != "") {
				$this->flux .= ($a [0] != "") ? "<loc>" . $this->cleanURL ( $a [0] ) . "</loc>" . $this->nl : "";
			}
			array_shift ( $a );
			$this->flux .= "</url>" . $this->nl;
			$this->addURL ( $a );
		
		}
	
	}
	
	/** 
	 * Mysql parser function.
	 *
	 * @param	Resource	$o	The MySQL resource to parse
	 * 
	 * @return	Void
	 */
	function addMysqlURL($o) {
		
		while ( $res = mysql_fetch_object ( $o ) ) {
			$a = $this->ObjectToArray ( $res );
			$this->add ( $a );
		}
	}
	/** 
	 * Folder parser function.
	 *
	 * @param	String	$path	The path to analyse end parse
	 * @param	Array	$option	Option for the analyse. 
	 * url: the url to add before the name files. Exemple: http://www.test.com/
	 * hidden: list of files extension to hide (exemple : .htaccess,.txt)
	 * resursive: bolean, specify if the parser must browser the forlder recursively or not
	 *
	 * 
	 * @return	Void
	 */
	function addFolderURL($path, $option = array()) {
		
		$dir = opendir ( $path );
		$restrict = explode ( ",", $option ["hidden"] );
		while ( ($file = readdir ( $dir )) !== false ) {
			if ($file == "." || $file == "..")
				continue;
			$file = $path . "/" . $file;
			if (! is_dir ( $file )) {
				if (! in_array ( strrchr ( $file, '.' ), $restrict )) {
					$this->flux .= "<url>" . $this->nl;
					$this->flux .= "<loc>" . $this->cleanURL ( str_replace ( "../", "", $option ["url"] . $file ) ) . "</loc>" . $this->nl;
					$this->flux .= "</url>" . $this->nl;
				}
			} else {
				if ($option ["recursive"]) {
					$this->addFolderURL ( $file, $option );
				}
			}
		}
	
	}
	
	/*-------------------------------------------------USEFUL FUNCTIONS-------------------------------*/
	
	/** 
	 * Check if an array is multi-dimensional or not
	 *
	 * @param	Array	$a	The array to analyse
	 * 
	 * @return	Bolean 
	 */
	
	function isMultiDimensional($a) {
		$ism = 0;
		for($i = 0; $i < count ( $a ); $i ++) {
			if (isset( $a [$i]) && is_array ( $a [$i] )) {
				$ism = 1;
			}
		}
		return $ism;
	}
	
	/** 
	 * Check if an array is an associative array or not
	 *
	 * @param	Array	$a	The array to analyse
	 * 
	 * @return	Bolean 
	 */
	
	function isAssocArray($a) {
		return (isset($a [0]) && $a [0]) != "" ? false : true;
	}
	/** 
	 * Convert an Object to Array
	 *
	 * @param	Object	$o	The Object to convert
	 * 
	 * @return	Array
	 */
	function objectToArray($o) {
		
		$a = array ();
		while ( list ( $k, $v ) = each ( $o ) ) {
			$a [$k] = $v;
		}
		return $a;
	}
	
	/** 
	 * Convert a string whith htmlentities and utf8 encode.
	 *
	 * @param	String	$s	The string to clean 
	 * 
	 * @return	String
	 */
	function cleanURL($s) {
		$s = htmlentities ( $s, ENT_QUOTES, "UTF-8" );
		$s = utf8_encode ( $s );
		return $s;
	}
	
	/** 
	 * Write a file to the specified file.
	 *
	 * @param	String	$file	The path to write the file
	 * @param	String	$string	The content to write
	 * 
	 * @return	Void
	 */
	
	function makerFile($file, $string) {
		$f = fopen ( $file, 'w+' );
		ftruncate ( $f, 0 );
		fwrite ( $f, $string );
		fclose ( $f );
	}

}

?>